package org.testis.orm.refinedclasses;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import org.orm.PersistentException;
import org.testis.orm.classes.T_test_label;
import org.testis.orm.classes.T_test_labelpairs;
import org.testis.orm.classes.T_test_stepcontainer;
import org.testis.orm.refinedclasses.TestDesignTreeRefined.TestDesignTreeParameters;
import org.testis.utils.middleware.LabelDataHandler;
import org.testis.utils.middleware.LabelUtils;
import org.testis.utils.middleware.TestDesign;

/**
 * 
 * @author Cahit Emir Erel
 */
public class TestCaseGroupRefined extends DesignPart implements ILabelContainer {

    private T_test_stepcontainer m_reference;
    public static final String DEFAULT_TYPE = "Regression";

    public TestCaseGroupRefined(T_test_stepcontainer reference) {
	setReference(reference);
    }

    synchronized public TestCaseGroupRefined createRefinedDatabaseCopy()
	    throws PersistentException {
	return new TestCaseGroupRefined(createDatabaseCopy());
    }

    public String[] getLabels() {
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    String[] labels = new String[getReference().t_test_labelpairs
		    .size()];
	    Iterator it = getReference().t_test_labelpairs.getIterator();
	    int i = 0;
	    while (it.hasNext()) {
		labels[i] = it.next().toString();
		i++;
	    }
	    return labels;
	} else {
	    return new String[] { DEFAULT_TYPE };
	}
    }

    public boolean hasLabel(String token) {
	boolean result = false;
	String[] labels = getLabels();
	for (int i = 0; i < labels.length; i++) {
	    if (labels[i].equals(token)) {
		result = true;
		break;
	    }
	}
	return result;
    }

    private T_test_stepcontainer createDatabaseCopy()
	    throws PersistentException {
	T_test_stepcontainer newContainer = new T_test_stepcontainer();
	newContainer.setContainerTypeId(this.getReference()
		.getContainerTypeId());
	newContainer.setDescription(this.getReference().getDescription());
	newContainer.setName(this.getReference().getName());
	if (newContainer.save()) {
	    return newContainer;
	} else {
	    throw new PersistentException(
		    "Unable to create database copy of Test Case Group: "
			    + this);
	}
    }

    @Override
    public String toString(TestDesignTreeNode treeNode) {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append(this.toString());
	    Boolean val = treeNode.getReference().getParameterBooleanValue(
		    TestDesignTreeParameters.RunAlways.name());
	    if (val != null) {
		buffer.append("\nRun Always: " + val);
	    }
	    // buffer.append("\nLabels:" + getLabelsAsString(false));
	    buffer.append("\n\n\nLabels: ");
	    T_test_label[] labels = getLabelsAsArray();
	    if (labels != null && labels.length > 0) {
		for (int i = 0; i < labels.length; i++) {
		    buffer.append("\n\t" + labels[i].getName());
		}
	    } else {
		buffer.append("\tNo labels found");
	    }
	    return buffer.toString();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    @Override
    public String toString() {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append("Type: "
		    + TestDesign.getDesignPartTypeName(this.getReference()
			    .getContainerTypeId()) + "\n");

	    buffer.append("Name: " + this.getName());
	    buffer.append("\nStep Container Id: " + this.getId());
	    buffer.append("\nDescription: "
		    + this.getReference().getDescription());
	    return buffer.toString();

	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    public T_test_stepcontainer getReference() {
	return m_reference;
    }

    private void setReference(T_test_stepcontainer reference) {
	if (reference == null) {
	    throw new NullPointerException();
	}
	m_reference = reference;
    }

    public String getTypeName() {
	return TestDesign.getDesignPartTypeName(this.getReference()
		.getContainerTypeId());
    }

    private int compare(Comparable source) {
	return Comparable.EXACT;
    }

    public int compare(Comparable source, Comparable treeReference) {
	TestDesignTreeNode src = (TestDesignTreeNode) source;
	TestDesignTreeNode thisTree = (TestDesignTreeNode) treeReference;
	String srcval = src.getReference().getParameterValue(
		TestDesignTreeParameters.RunAlways.name());
	String destTreeval = thisTree.getReference().getParameterValue(
		TestDesignTreeParameters.RunAlways.name());

	if (srcval == null ? destTreeval != null : !srcval.equals(destTreeval)) {
	    return Comparable.DIFFERENT_PROPERTIES;
	}
	return compare(src.getObject());
    }

    private boolean hasSameStaticParameters(HashMap<String, Object> params,
	    Comparable treeReference) {
	String description = (String) params.get("description");
	String runAlways = (String) params.get("runAlways");
	LinkedList<String> labels = (LinkedList<String>) params.get("labels");

	TestDesignTreeNode testDesignTreeNode = (TestDesignTreeNode) treeReference;
	TestCaseGroupRefined tcgRefined = (TestCaseGroupRefined) ((TestDesignTreeNode) testDesignTreeNode)
		.getObject();

	if (tcgRefined != null) {
	    HashMap myLabels = tcgRefined.getLabelsAsHashMap();
	    if (myLabels.size() != labels.size()) {
		return false;
	    }
	    Iterator iterator = myLabels.keySet().iterator();
	    while (iterator.hasNext()) {
		T_test_label myLabel = (T_test_label) myLabels.get(iterator
			.next());
		if (!labels.contains(myLabel.getName())) {
		    return false;
		}
	    }
	}
	String val = testDesignTreeNode.getReference().getParameterValue(
		TestDesignTreeParameters.RunAlways.name());
	if ((val == null ? runAlways == null : val.equals(runAlways))
		&& getReference().getDescription().equals(description)) {
	    return true;
	} else {
	    return false;
	}
    }

    public boolean compareParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return hasSameStaticParameters(params, treeTreference);
    }

    public boolean hasSameRunTimeParams(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return true;
    }

    public T_test_label[] getLabelsAsArray() {
	T_test_label[] labels = null;
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    labels = new T_test_label[labelpairs.length];
	    for (int i = 0; i < labelpairs.length; i++) {
		labels[i] = handler.getLabelById(labelpairs[i].getLabelId());
	    }
	}
	return labels;
    }

    public HashMap getLabelsAsHashMap() {
	HashMap result = new HashMap();
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    for (int i = 0; i < labelpairs.length; i++) {
		T_test_label label = handler.getLabelById(labelpairs[i]
			.getLabelId());
		result.put(label.getId(), label);
	    }
	}
	return result;
    }

    public String getLabelsAsString(boolean inheritance) {
	return LabelUtils
		.convertLabelsToString(getLabelsAsArray(), inheritance);
    }

    public boolean matchesLabelPattern(String regex) {
	return LabelUtils.matchesLabelPattern(regex, getLabelsAsString(true));
    }
}
